home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
379_01
/
zoo210s.zoo
/
zooext.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-12
|
23KB
|
659 lines
#ifndef LINT
/* derived from: zooext.c 2.21 88/08/24 02:39:04 */
/*$Source: /usr/home/dhesi/zoo/RCS/zooext.c,v $*/
/*$Id: zooext.c,v 1.9 91/07/09 01:54:13 dhesi Exp $*/
static char sccsid[]="$Source: /usr/home/dhesi/zoo/RCS/zooext.c,v $\n\
$Id: zooext.c,v 1.9 91/07/09 01:54:13 dhesi Exp $";
#endif /* LINT */
/*
Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
(C) Copyright 1988 Rahul Dhesi -- All rights reserved
(C) Copyright 1991 Rahul Dhesi -- All rights reserved
*/
/* Extract file from archive. Extracts files specified in parameter-list
from archive zoo_path. If none specified, extracts all files from
archive. */
#include "options.h"
#include "zoo.h"
#include "parse.h" /* defines struct for parse() */
#include "portable.h" /* portable I/O definitions */
#include "machine.h" /* machine-specific declarations */
#include "zooio.h"
#include "various.h"
#ifndef NOSIGNAL
#include <signal.h>
#endif
#include "zoofns.h"
#ifdef MODE_BIN /* will need fileno() from stdio.h */
# include <stdio.h>
#endif
void makepath PARMS((char *));
int needed PARMS((char *, struct direntry *, struct zoo_header *));
void putstr PARMS((char *));
#ifdef FATTR
int setfattr PARMS ((char *, unsigned long));
#endif /* FATTR */
extern int quiet;
#include "errors.i"
/* Following two are used by ctrl_c() also, hence declared here */
char extfname[LFNAMESIZE]; /* filename of extracted file */
char prtfname[LFNAMESIZE]; /* name of extracted file on screen */
static ZOOFILE this_file; /* file to extract */
static int tofile; /* true if not pipe or null device */
extern unsigned int crccode;
extern char *out_buf_adr; /* address of output buffer */
void zooext(zoo_path, option)
char *zoo_path, *option;
{
char *whichname; /* which name to extract */
char matchname[PATHSIZE]; /* for pattern matching only */
#ifndef NOSIGNAL
T_SIGNAL (*oldsignal)(); /* to save previous SIGINT handler */
#endif
ZOOFILE zoo_file; /* open archive */
long next_ptr; /* pointer to within archive */
struct zoo_header zoo_header; /* header for archive */
int status; /* error status */
int exit_status = 0; /* exit status */
int error_message; /* Whether to give error message */
unsigned long disk_space; /* disk space left */
int matched = 0; /* Any files matched? */
int overwrite = 0; /* force overwrite of files? */
int supersede = 0; /* supersede newer files? */
int needdel = 0; /* extract deleted files too */
int usepath = 2; /* use path for extraction */
int todot = 0; /* extract relative to . */
int badcrc_count = 0; /* how many files with bad CRC */
int bad_header = 0; /* to avoid spurious messages later */
long fiz_ofs = 0; /* offset where to start */
long dat_ofs = 0; /* .. and offset of file data */
int pipe = 0; /* are we piping output? */
int null_device = 0; /* are we sending to null device? */
#ifndef PORTABLE
int fast_ext = 0; /* fast extract as *.?Z? */
int alloc_size; /* disk allocation unit size */
#endif
struct direntry direntry; /* directory entry */
int first_dir = 1; /* first dir entry seen? */
static char extract_ver[] = "Zoo %d.%d is needed to extract %s.\n";
static char no_space[] = "Insufficient disk space to extract %s.\n";
while (*option) {
switch (*option) {
#ifndef PORTABLE
case 'z': fast_ext++; break;
#endif
case 'x':
case 'e': break;
case 'N': null_device++; break;
case 'O': overwrite += 2; break;
case 'o': overwrite++; break;
case 'p': pipe++; break;
case 'S': supersede++; break;
case 'd': needdel++; break;
case 'q': quiet++; break;
case ':': usepath = 0; break;
case '/': usepath++; break;
case '.': todot++; break;
case '@': /* if @m,n specified, fiz_ofs = m, dat_ofs = n */
{
char *comma_pos;
++option;
comma_pos = strchr(option, ',');
if (comma_pos != NULL) {
dat_ofs = calc_ofs (comma_pos + 1);
*comma_pos = '\0';
}
fiz_ofs = calc_ofs(option);
goto no_more;
}
default:
prterror ('f', inv_option, *option);
/* break; */
}
option++;
}
no_more: /* come from exit in while loop above */
if (overwrite == 1) /* must be at least 2 to begin with */
overwrite--;
if (null_device && pipe) {
prterror ('f', inv_option, 'p');
pipe = 0;
}
if (overwrite && pipe)
prterror ('w', option_ignored, 'O');
#ifndef PORTABLE
if (null_device && fast_ext) {
prterror ('w', inv_option, 'N');
null_device = 0;
}
#endif
tofile = !pipe && !null_device; /* sending to actual file */
zoo_file = zooopen(zoo_path, Z_READ);
if (zoo_file == NOFILE)
prterror ('f', could_not_open, zoo_path);
if (fiz_ofs != 0L) { /* if offset specified, start there */
prterror ('m', start_ofs, fiz_ofs, dat_ofs);
zooseek (zoo_file, fiz_ofs, 0);
} else {
/* read header */
frd_zooh (&zoo_header, zoo_file);
if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L) {
prterror ('w', failed_consistency);
bad_header++;
exit_status = 1;
}
zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
}
#ifndef PORTABLE
disk_space = space (0, &alloc_size); /* remember disk space left */
#else
disk_space = MAXLONG; /* infinite disk space */
#endif
/* if piping output we open the output device just once */
if (null_device) {
this_file = NULLFILE;
} else if (pipe)
this_file = STDOUT; /* standard output */
while (1) {
frd_dir (&direntry, zoo_file);
if (direntry.zoo_tag != ZOO_TAG) {
long currpos, zoolength;
prterror ('F', invalid_header);
/* Note: if header was bad, there's no point trying to find
how many more bytes aren't processed -- our seek position is
likely very wrong */
if (!bad_header)
if ((currpos = zootell (zoo_file)) != -1L)
if (zooseek (zoo_file, 0L, 2) != -1)
if ((zoolength = zootell (zoo_file)) != -1L)
printf (cant_process, zoolength - currpos);
zooexit (1);
}
if (direntry.next == 0L) { /* END OF CHAIN */
break; /* EXIT on end of chain */
}
/* when first direntry read, change dat_ofs from abs. pos. to rel. offset */
if (first_dir && dat_ofs != 0) {
dat_ofs -= direntry.offset;
first_dir = 0;
}
next_ptr = direntry.next + dat_ofs; /* ptr to next dir entry */
whichname = choosefname(&direntry); /* which filename */
whichname = str_dup(whichname); /* bug fix */
fixfname(whichname); /* fix syntax */
strcpy (matchname, fullpath (&direntry)); /* get full pathname */
if (zoo_header.vdata & VFL_ON)
add_version (matchname, &direntry); /* add version suffix */
/* if extraction to subtree rooted at curr dir, modify pathname */
#if 0
#ifdef DIR_LBRACK
if (todot && direntry.dirname[0] == *DIR_LBRACK &&
direntry.dirname[1] != *CUR_DIR) {
char tmpstr[PATHSIZE];
strcpy (tmpstr, DIR_LBRACK);
strcat (tmpstr, CUR_DIR);
strcat (tmpstr, &direntry.dirname[1]);
strcpy (direntry.dirname, tmpstr);
}
#endif
#endif
/* hard-coded '/' should be eventually removed */
if (todot && *direntry.dirname == '/') {
char tmpstr[PATHSIZE];
strcpy(tmpstr, direntry.dirname);
strcpy(direntry.dirname,CUR_DIR);
strcat(direntry.dirname, tmpstr);
}
/* matchname now holds the fu